package com.cloud.pole.user.service.impl;

import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import com.ace.cache.api.CacheAPI;
import com.cloud.pole.api.user.BaseUserApi;
import com.cloud.pole.api.weixin.WxUserApi;
import com.cloud.pole.common.constant.CacheConstant;
import com.cloud.pole.common.constant.CommonConstants;
import com.cloud.pole.common.constant.UserConstant;
import com.cloud.pole.common.exception.BaseException;
import com.cloud.pole.common.exception.auth.UserInvalidException;
import com.cloud.pole.common.msg.ApiRestResponse;
import com.cloud.pole.common.util.jwt.IJWTInfo;
import com.cloud.pole.common.util.jwt.JWTInfo;
import com.cloud.pole.common.util.jwt.JwtTokenUtil;
import com.cloud.pole.feign.IVerifyCodeService;
import com.cloud.pole.feign.IWxUserService;
import com.cloud.pole.user.biz.BaseUserBiz;
import com.cloud.pole.user.biz.CpChannelPersonBiz;
import com.cloud.pole.user.biz.authorized.UserAuthorizedWxBiz;
import com.cloud.pole.user.model.entity.BaseUser;
import com.cloud.pole.user.model.entity.CpChannelPerson;
import com.cloud.pole.user.model.entity.authorized.UserAuthorizedWx;
import com.cloud.pole.user.service.AuthService;
import com.cloud.pole.util.CacheApiUtil;
import com.cloud.pole.util.ChannelPersonUtil;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class AuthServiceImpl implements AuthService {
    private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12);

    @Autowired
    private CacheAPI cacheAPI;
	@Autowired
    private BaseUserBiz userBiz;
    @Autowired
    private IVerifyCodeService verifyCodeService;
    @Autowired
    private CacheApiUtil cacheApiUtil;    
	@Autowired
    private UserAuthorizedWxBiz userAuthorizedWxBiz;
	@Autowired
	private IWxUserService  wxUserService;
	
	@Autowired
	private CpChannelPersonBiz channelPersonBiz;

    @Override
    public BaseUserApi login(String userName, String userPwd, String openId) throws Exception {
    	BaseUser user = userBiz.getUserByUserName(userName);
    	BaseUserApi userVo = new BaseUserApi();
    	if (user != null && encoder.matches(userPwd, user.getPassWord())) {
    		if(StringUtils.isNotBlank(user.getMobile())){
    			//查询cp_channel_person有没有对应的手机号
    			ChannelPersonUtil.checkChannelPerson(user.getMobile(), user, channelPersonBiz);
    			userBiz.updateSelectiveById(user);
    		}
    		
        	JWTInfo jwtInfo = new JWTInfo(user.getUserName(), JWTInfo.USER_TYPE_BASE, Long.toString(user.getUserId()), user.getNickName(), user.getRealName());
        	String token = cacheApiUtil.generateCatchToken(jwtInfo);
            BeanUtils.copyProperties(user, userVo);
        	//获取用户信息
        	userVo.setToken(token);
        	//绑定微信
        	if(!StringUtils.isEmpty(openId)) {
        		addUserAuthorizedWx(openId, userVo.getUserId(), userVo.getUserName());
        	}
        	return userVo;
        }
        throw new UserInvalidException("用户不存在或账户密码错误!");
    }
    
    /**
     *  授权登录
     * @param openId
     * @param userId
     * @param userName
     */
    public void addUserAuthorizedWx(String openId, Long userId, String userName) {
    	//获取微信用户信息
		ApiRestResponse<WxUserApi> apiRestResponse =  wxUserService.getWxUser(openId);
		if(apiRestResponse.getStatus() != CommonConstants.STATUS_OK_CODE) {
			throw new BaseException(apiRestResponse.getStatus(), apiRestResponse.getMessage());
		}
		WxUserApi wxUserApi = apiRestResponse.getData();
	    if(wxUserApi == null) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "openId错误");
	    }
		//微信授权查看是否授权给其他账户
	    UserAuthorizedWx userAuthorizedWx = userAuthorizedWxBiz.selectByOpenId(openId);
	    if(userAuthorizedWx != null && userAuthorizedWx.getUserId().longValue() != userId.longValue()) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "微信绑定了其他账号");
	    }
	    //绑定微信
	    if(userAuthorizedWx == null) {
		    userAuthorizedWx = new UserAuthorizedWx();
	  		userAuthorizedWx.setAppId(wxUserApi.getAppId());
	  		userAuthorizedWx.setAuthorizedNote("");
	  		userAuthorizedWx.setAuthorizedStatus(UserAuthorizedWx.AUTHORIZED_STATUS_OK);
	  		userAuthorizedWx.setAuthorizedTime(new Date());
	  		userAuthorizedWx.setOpenId(wxUserApi.getOpenId());
	  		userAuthorizedWx.setUserId(userId);
	  		userAuthorizedWx.setUserName(userName);
	  		userAuthorizedWx.setWxAppId(wxUserApi.getWxAppId());
	  		userAuthorizedWxBiz.insert(userAuthorizedWx);
	    }
    }

	@Override
	public BaseUserApi userTokenLogin(String token) throws Exception {
    	validate(token);
    	JWTInfo jwtInfo = (JWTInfo)JwtTokenUtil.getInfoFromToken(token);
    	BaseUser baseUser = userBiz.getUserByUserName(jwtInfo.getUniqueName());
    	
    	if(StringUtils.isNotBlank(baseUser.getMobile())){
    		//查询cp_channel_person有没有对应的手机号
    		ChannelPersonUtil.checkChannelPerson(baseUser.getMobile(), baseUser, channelPersonBiz);
			userBiz.updateSelectiveById(baseUser);
		}
    	
    	BaseUserApi userVo = new BaseUserApi();
        BeanUtils.copyProperties(baseUser, userVo);
		return userVo;
	}
	
    @Override
    public boolean validate(String token) throws Exception {
    	JWTInfo jwtInfo = (JWTInfo)JwtTokenUtil.getInfoFromToken(token);
    	BaseUser user = userBiz.getUserByUserName(jwtInfo.getUniqueName());
    	String strCatchToken = cacheAPI.get(CacheConstant.BASE_USER_TOKEN_KEY + ":" + jwtInfo.getUniqueName());
    	log.debug("读取缓存：token=" + strCatchToken);
    	//获取用户信息，可以把用户账号无效等状态加到业务处理
    	if(StringUtils.isEmpty(strCatchToken)) {
    		log.debug("写入缓存：token=" + token);
    		strCatchToken = token;
        	cacheAPI.set(CacheConstant.BASE_USER_TOKEN_KEY + ":" + jwtInfo.getUniqueName() , token, CacheConstant.BASE_USER_TOKEN_CATCH_EXPIRE);
    	}
    	if (user == null || user.getLoginLockStatus() == 1) {
    		throw new BaseException(CommonConstants.USER_STATUS_ERROR, CommonConstants.USER_STATUS_ERROR_MESSAGE);
    	}
    	if(!StringUtils.equals(token, strCatchToken)) {
    		throw new BaseException(CommonConstants.TOKEN_ERROR_EXISTS_CODE, CommonConstants.TOKEN_ERROR_EXISTS_MSSSAGE);
    	}
    	return true;    
    }

    @Override
    public String refresh(String oldToken) throws Exception {
    	IJWTInfo jwtInfo = JwtTokenUtil.getInfoFromToken(oldToken);
        return JwtTokenUtil.generateToken(jwtInfo, CacheConstant.BASE_USER_TOKEN_EXPIRE);
    }

	@Override
	public BaseUserApi smsLogin(String mobile, String mobileArea, String verifyCode, String openId) throws Exception {
		BaseUserApi baseUserVo = new BaseUserApi();
		//判断验证码是否有效
		ApiRestResponse<Boolean> checkResponse = verifyCodeService.checkVerifyCode(mobileArea, mobile, UserConstant.VERIFY_CODE_LOGIN, verifyCode);
		if(checkResponse.getStatus() != CommonConstants.STATUS_OK_CODE) {
			throw new BaseException(checkResponse.getStatus(), checkResponse.getMessage());
		}
		Boolean checkResult = checkResponse.getData();
		if(checkResult.booleanValue() == false) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "验证码错误");
		}
		BaseUser userParam = new BaseUser();
		userParam.setMobile(mobile);
		userParam.setMobileArea(mobileArea);
		BaseUser baseUser = userBiz.selectOne(userParam);
		if(baseUser == null) {
			String userNickName = mobile.substring(0 , 3) + "****" + mobile.substring(7 , mobile.length());
			baseUser = new BaseUser();
			baseUser.setMobile(mobile);
			baseUser.setUserName(mobileArea + mobile);
			baseUser.setPassWord("");
			baseUser.setMobileArea(mobileArea);
			baseUser.setCreateTime(new Date());
			baseUser.setWeixin("");
			baseUser.setOriginTag(BaseUser.USER_ORIGIN_TAG_WEB);
			baseUser.setUserStatus(BaseUser.USER_STATUS_EFFECTIVE);
			baseUser.setNickName(userNickName);
			userBiz.insertUseGeneratedKeys(baseUser);
		}
		
		//查询cp_channel_person有没有对应的手机号
		ChannelPersonUtil.checkChannelPerson(mobile, baseUser, channelPersonBiz);
		userBiz.updateSelectiveById(baseUser);
		
		//绑定微信
    	if(!StringUtils.isEmpty(openId)) {
    		addUserAuthorizedWx(openId, baseUser.getUserId(), baseUser.getUserName());
    	}
    	JWTInfo jwtInfo = new JWTInfo(baseUser.getUserName(), JWTInfo.USER_TYPE_BASE, Long.toString(baseUser.getUserId()), baseUser.getNickName(), baseUser.getRealName());
		BeanUtils.copyProperties(baseUser, baseUserVo);
		String token = cacheApiUtil.generateCatchToken(jwtInfo);
    	//获取用户信息
        baseUserVo.setToken(token);
		return baseUserVo;
	}

	/**
	 * 使用微信opendId登录
	 */
	@Override
	public BaseUserApi wxLogin(String opendId) throws Exception {
		UserAuthorizedWx userAuthorizedWx = userAuthorizedWxBiz.selectByOpenId(opendId);
		if(userAuthorizedWx == null || userAuthorizedWx.getAuthorizedStatus() != UserAuthorizedWx.AUTHORIZED_STATUS_OK) {
			throw new BaseException(CommonConstants.TOKEN_ERROR_CODE, "微信未绑定");
		}
		BaseUser baseUser = userBiz.getUserByUserName(userAuthorizedWx.getUserName());
		BaseUserApi userVo = null;
		if(baseUser != null) {
			if(StringUtils.isNotBlank(baseUser.getMobile())){
				//查询cp_channel_person有没有对应的手机号
				ChannelPersonUtil.checkChannelPerson(baseUser.getMobile(), baseUser, channelPersonBiz);
				userBiz.updateSelectiveById(baseUser);
			}
			
		    userVo = new BaseUserApi();
	        JWTInfo jwtInfo = new JWTInfo(baseUser.getUserName(), JWTInfo.USER_TYPE_BASE, 
	        		Long.toString(baseUser.getUserId()), baseUser.getNickName(), baseUser.getRealName());
	        String token = cacheApiUtil.generateCatchToken(jwtInfo);
	        BeanUtils.copyProperties(baseUser, userVo);
	        //获取用户信息
	        userVo.setToken(token);
		}
        return userVo;
	}

	/**
	 * 小程序绑定手机号
	 */
	@Override
	public BaseUserApi wxUserBind(String mobile, String mobileArea, String openId, Integer userType) {
		//获取微信用户信息
		ApiRestResponse<WxUserApi> apiRestResponse =  wxUserService.getWxUser(openId);
		if(apiRestResponse.getStatus() != CommonConstants.STATUS_OK_CODE) {
			throw new BaseException(apiRestResponse.getStatus(), apiRestResponse.getMessage());
		}
		WxUserApi wxUserApi = apiRestResponse.getData();
		if(wxUserApi == null) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "openId错误");
		}		
		BaseUserApi baseUserVo = new BaseUserApi();
		BaseUser userParam = new BaseUser();
		userParam.setMobile(mobile);
		userParam.setMobileArea(mobileArea);
		BaseUser baseUser = userBiz.selectOne(userParam);
		UserAuthorizedWx userAuthorizedWx = null;
		boolean boolModify = false;
		if(baseUser != null) {
			//账号授权给其他微信账号
		    userAuthorizedWx = userAuthorizedWxBiz.selectByUserId(baseUser.getUserId(), wxUserApi.getWxAppId());
		    
		    if(userAuthorizedWx != null && !StringUtils.equals(userAuthorizedWx.getOpenId(), openId)){
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "账号绑定了其他微信");
		    }
			//微信授权查看是否授权给其他账户
		    userAuthorizedWx = userAuthorizedWxBiz.selectByOpenId(openId);
		    if(userAuthorizedWx != null && userAuthorizedWx.getUserId().longValue() != baseUser.getUserId().longValue()) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "微信绑定了其他账号");
		    }
		    //更新用户userType 级别只能从小往上修改
		    if(baseUser.getUserType().intValue() < userType.intValue()) {
		    	boolModify = true;
		    	baseUser.setUserType(userType);
		    }
		    //更新手机号码
		    if(StringUtils.isEmpty(baseUser.getMobile())) {
		    	boolModify = true;
		    	baseUser.setMobile(mobileArea);
		    	baseUser.setMobileArea(mobileArea);
		    }
		    //更新头像
		    if(StringUtils.isEmpty(baseUser.getIconPath()) && StringUtils.isEmpty(wxUserApi.getAvatarUrl())) {
		    	boolModify = true;
		    	baseUser.setIconPath(wxUserApi.getAvatarUrl());
		    }
		    //更新昵称
		    if(StringUtils.isEmpty(baseUser.getNickName()) && StringUtils.isEmpty(wxUserApi.getNickName())) {
		    	boolModify = true;
		    	baseUser.setNickName(wxUserApi.getNickName());
		    }
		    if(boolModify) {
		    	userBiz.updateSelectiveById(baseUser);
		    }
		}
		if(baseUser == null) {
			baseUser = new BaseUser();
			baseUser.setMobile(mobile);
			baseUser.setUserName(mobileArea + mobile);
			baseUser.setPassWord("");
			baseUser.setMobileArea(mobileArea);
			baseUser.setCreateTime(new Date());
			baseUser.setWeixin("");
			baseUser.setOriginTag(BaseUser.USER_ORIGIN_TAG_WEIXIN);
			baseUser.setUserStatus(BaseUser.USER_STATUS_EFFECTIVE);
			baseUser.setNickName(wxUserApi.getNickName());
			baseUser.setIconPath(wxUserApi.getAvatarUrl());
			baseUser.setUserType(userType);
			userBiz.insertUseGeneratedKeys(baseUser);
		}
		 //绑定微信
	    if(userAuthorizedWx == null) {
		    userAuthorizedWx = new UserAuthorizedWx();
	  		userAuthorizedWx.setAppId(wxUserApi.getAppId());
	  		userAuthorizedWx.setAuthorizedNote("");
	  		userAuthorizedWx.setAuthorizedStatus(UserAuthorizedWx.AUTHORIZED_STATUS_OK);
	  		userAuthorizedWx.setAuthorizedTime(new Date());
	  		userAuthorizedWx.setOpenId(wxUserApi.getOpenId());
	  		userAuthorizedWx.setUserId(baseUser.getUserId());
	  		userAuthorizedWx.setUserName(baseUser.getUserName());
	  		userAuthorizedWx.setWxAppId(wxUserApi.getWxAppId());
	  		userAuthorizedWxBiz.insert(userAuthorizedWx);
	    }
		JWTInfo jwtInfo = new JWTInfo(baseUser.getUserName(), JWTInfo.USER_TYPE_BASE, Long.toString(baseUser.getUserId()), baseUser.getNickName(), baseUser.getRealName());
		BeanUtils.copyProperties(baseUser, baseUserVo);
		String token = cacheApiUtil.generateCatchToken(jwtInfo);
		//获取用户信息
		baseUserVo.setToken(token);
		return baseUserVo;
	}
}
